﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace BlindData
{
	public static class NameGenerator
	{
		private static IDictionary<int, int> _maleFirstNameIndexes;
		private static IDictionary<int, int> _femaleFirstNameIndexes;
		private static IDictionary<int, int> _lastNameIndexes;

		static NameGenerator()
		{
			_maleFirstNameIndexes = GetNameIndexes(Resources.MaleFirstNameFile);
			_femaleFirstNameIndexes = GetNameIndexes(Resources.FemaleFirstNameFile);
			_lastNameIndexes = GetNameIndexes(Resources.LastNameFile);
		}

		/// <summary>
		/// Returns a random first name.
		/// </summary>
		/// <returns></returns>
		public static string FirstName(this INext<string> next)
		{
			if (next == null)
			{
				throw new ArgumentNullException("next");
			}
			if (next.Generator.Next<bool>().Value())
			{
				return GetName(next, _maleFirstNameIndexes, Resources.MaleFirstNameFile);
			}
			else
			{
				return GetName(next, _femaleFirstNameIndexes, Resources.FemaleFirstNameFile);
			}
		}

		/// <summary>
		/// Returns a random last name.
		/// </summary>
		/// <returns></returns>
		public static string LastName(this INext<string> next)
		{
			if (next == null)
			{
				throw new ArgumentNullException("next");
			}
			return GetName(next, _lastNameIndexes, Resources.LastNameFile);
		}

		private static IDictionary<int, int> GetNameIndexes(string nameFile)
		{
			var indexes = new Dictionary<int, int>();

			var reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(nameFile));
			var names = reader.ReadToEnd();
			reader.Close();

			var currentIndex = 0;
			var currentCount = 0;
			for (int i = 0; i < names.Length; i++)
			{
				if (names[i] == ',')
				{
					indexes.Add(currentIndex, currentCount);
					currentIndex = i + 1;
					currentCount = 0;
				}
				else
				{
					currentCount++;
				}
			}

			return indexes;
		}

		private static string GetName(INext<string> next, IDictionary<int, int> nameIndexes, string nameFile)
		{
			var reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(nameFile));
			var nameIndex = next.Generator.Next<IList<int>>().Value(nameIndexes.Keys.ToList());
			var nameLength = nameIndexes[nameIndex];

			var nameArray = new char[nameLength];
			reader.BaseStream.Seek(nameIndex, SeekOrigin.Begin);
			reader.ReadBlock(nameArray, 0, nameLength);
			return new String(nameArray);
		}
	}
}
